package com.gzs.learn.payment.service.api.impl;

import com.gzs.learn.common.util.HttpUtil.Response;
import com.gzs.learn.payment.inf.exception.PaymentException;
import com.gzs.learn.payment.model.cfg.PaycfgChannel;
import com.gzs.learn.payment.model.cfg.TokenYinlian;
import com.gzs.learn.payment.model.unionpay.UnionpayConstant;
import com.gzs.learn.payment.model.unionpay.notify.UnionpayNotify;
import com.gzs.learn.payment.model.unionpay.pay.UnionpayRequest;
import com.gzs.learn.payment.model.unionpay.pay.UnionpayResult;
import com.gzs.learn.payment.model.unionpay.query.UnionpayQuery;
import com.gzs.learn.payment.model.unionpay.query.UnionpayQueryResult;
import com.gzs.learn.payment.service.api.IUnionpayService;
import com.gzs.learn.payment.util.AssertUtil;
import com.gzs.learn.payment.util.SignUtil;
import org.apache.http.NameValuePair;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

import static com.gzs.learn.common.util.HttpUtil.doPost;
import static com.gzs.learn.common.util.HttpUtil.obj2Pair;
import static com.gzs.learn.payment.util.AssertUtil.*;
import static com.gzs.learn.payment.util.CommonsUtil.*;


/**
 *
 * @author guanzhisong
 * @date 2017年3月30日
 */
@Component
public class UnionpayServiceImpl extends BaseUnionpay implements IUnionpayService {
    @Override
    public UnionpayResult unionpayRequest(UnionpayRequest unionpayRequest, PaycfgChannel paycfgChannel) {
        // yinlianPay
        checkBlankStr(unionpayRequest.getOrderId(), "orderid is blank");
        checkBlankStr(unionpayRequest.getTxnTime(), "txtTime can not be blank");
        checkNumberPositive(unionpayRequest.getTxnAmt(), "txtAmt can not be blank");
        checkBlankStr(unionpayRequest.getBackUrl(), "backurl can not be blank");

        // 校验paycfgPla参数
        TokenYinlian tokenYinlian = convertToken(paycfgChannel.getToken(), TokenYinlian.class);
        checkToken(tokenYinlian);

        // 写入固定的的参数
        buildUnionpayInfo(unionpayRequest, tokenYinlian);
        String sign = SignUtil.yinlianSign(unionpayRequest, tokenYinlian);
        unionpayRequest.setSignature(sign);

        List<NameValuePair> listParam = obj2Pair(unionpayRequest);
        Response<String> resp = doPost(YINLIAN_TRANS, listParam, String.class);
        checkObjNotNull(resp, "call yinlian inf failed");
        checkArg(resp.isSuccess(), "call yinlian inf failed,result:" + resp.getEntity());
        UnionpayResult result = httpResultToObj(resp.getEntity(), UnionpayResult.class);
        AssertUtil.checkObjNotNull(result, "result can not be null");

        if (!SignUtil.yinlianSignVerify(result, tokenYinlian)) {
            throw new PaymentException("yinlian sign incorrent");
        }
        return result;
    }

    private void buildUnionpayInfo(UnionpayRequest unionpayRequest, TokenYinlian tokenYinlian) {
        unionpayRequest.setVersion(UnionpayConstant.VERSION);
        unionpayRequest.setEncoding(UnionpayConstant.ENCODING_UTF8);
        unionpayRequest.setTxnType(UnionpayConstant.TXNTYPE_XIAOFEI);
        unionpayRequest.setTxnSubType("01");
        unionpayRequest.setBizType("000201");
        unionpayRequest.setChannelType("08");
        unionpayRequest.setAccessType("0");
        unionpayRequest.setCurrencyCode("156");
        unionpayRequest.setMerId(tokenYinlian.getMerId());
        unionpayRequest.setCertId(tokenYinlian.getCertid());
        unionpayRequest.setSignMethod("01");
    }

    @Override
    public UnionpayNotify parseAsynResult(Map<String, String> inputMap, PaycfgChannel paycfgChannel) {
        // 校验weixinUnified参数
        if (null == inputMap || inputMap.size() <= 0) {
            throw new IllegalArgumentException("input map can not be blank");
        }
        // 校验paycfgPla参数
        TokenYinlian token = convertToken(paycfgChannel.getToken(), TokenYinlian.class);
        checkToken(token);

        // 将map转换为对象
        UnionpayNotify notify = map2Obj(inputMap, UnionpayNotify.class);
        checkObjNotNull(notify, "notify can not be null");
        // 检验签名是否正常
        boolean isSignRight = SignUtil.yinlianSignVerify(notify, token);
        if (!isSignRight) {
            throw new PaymentException("yinlian sign is not incorrect");
        }
        return notify;
    }

    @Override
    public UnionpayQueryResult unionpayQuery(UnionpayQuery unionpayQuery, PaycfgChannel paycfgChannel) {
        checkObjNotNull(unionpayQuery, "yinlian query not null");
        checkBlankStr(unionpayQuery.getOrderId(), "orderid is blank");
        checkBlankStr(unionpayQuery.getTxnTime(), "txtTime is blank");

        // 校验paycfgPla参数
        TokenYinlian tokenYinlian = convertToken(paycfgChannel.getToken(), TokenYinlian.class);
        checkToken(tokenYinlian);

        // 写入固定的的参数
        unionpayQuery.setVersion("5.0.0");
        unionpayQuery.setEncoding("UTF-8");
        unionpayQuery.setTxnType("00");
        unionpayQuery.setTxnSubType("00");
        unionpayQuery.setBizType("000201");
        unionpayQuery.setAccessType("0");
        unionpayQuery.setMerId(tokenYinlian.getMerId());
        unionpayQuery.setCertId(tokenYinlian.getCertid());
        unionpayQuery.setSignMethod("01");
        String sign = SignUtil.yinlianSign(unionpayQuery, tokenYinlian);
        unionpayQuery.setSignature(sign);

        List<NameValuePair> listParam = obj2Pair(unionpayQuery);
        Response<String> resp = doPost(QUERY, listParam, String.class);
        checkObjNotNull(resp, "call yinlian inf failed");
        checkArg(resp.isSuccess(), "call yinlian inf failed:" + resp.getEntity());
        UnionpayQueryResult result = httpResultToObj(resp.getEntity(), UnionpayQueryResult.class);

        checkObjNotNull(result, "yinlian query result is null");
        if (!SignUtil.yinlianSignVerify(result, tokenYinlian)) {
            throw new PaymentException("yinlian sign incorrect");
        }
        return result;
    }
}
